package org.lyq.erp.config.fileupload.ftp;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.lyq.erp.utils.string.ObjectEmptyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 上传的工具类FtpUtil
 * 
 * @author LYQ
 *
 */
public class FtpUtil {

	private static Logger logger = LoggerFactory.getLogger(FtpUtil.class);

	/**
	 * ftp上传文件方法 title:pictureUpload
	 * 
	 * @param picNewName  图片新名称--防止重名 例如："1.jpg"
	 * @param picSavePath 图片保存路径。注：最后访问路径是ftpConfig.getFTP_ADDRESS()+"/images"+picSavePath
	 * @param inputStream 要上传的文件（图片）
	 * @return 若上传成功，返回图片的访问路径，若上传失败，返回null
	 * @throws IOException
	 */
	public static String pictureFtpUpload(FtpConfig ftpConfig, String picNewName, String picSavePath,
			InputStream inputStream) throws IOException {

		if (!(ftpConfig != null && !ObjectEmptyUtils.isEmptyString(picNewName)
				&& !ObjectEmptyUtils.isEmptyString(picSavePath) && inputStream != null))
			return null;

		boolean flag = uploadFile(ftpConfig.getFtpAddress(), ftpConfig.getFtpPort(), ftpConfig.getFtpUsername(),
				ftpConfig.getFtpPassword(), ftpConfig.getFtpBasepath(), picSavePath, picNewName, inputStream);

		if (!flag)
			return null;

		return ftpConfig.getFileBaseUrl() + picSavePath + File.separator + picNewName;
	}

	/**
	 * ftp上传文件方法 videoFtpUpload
	 * 
	 * @param vidNewName  视频新名称--防止重名 例如："1.mp3"
	 * @param vidSavePath 视频保存路径。注：最后访问路径是ftpConfig.getFTP_ADDRESS()+"/video"+vidSavePath
	 * @param inputStream 要上传的文件（视频）
	 * @return 若上传成功，返回视频的访问路径，若上传失败，返回null
	 * @throws IOException
	 */
	public static String videoFtpUpload(FtpConfig ftpConfig, String vidNewName, String vidSavePath,
			InputStream inputStream) throws IOException {

		if (!(ftpConfig != null && ObjectEmptyUtils.isEmptyString(vidNewName)
				&& ObjectEmptyUtils.isEmptyString(vidSavePath) && inputStream != null))
			return null;

		boolean flag = uploadFile(ftpConfig.getFtpAddress(), ftpConfig.getFtpPort(), ftpConfig.getFtpUsername(),
				ftpConfig.getFtpPassword(), ftpConfig.getFtpBasepath() + File.separator + "video", vidSavePath,
				vidNewName, inputStream);

		if (!flag)
			return null;

		return ftpConfig.getFileBaseUrl() + vidSavePath + File.separator + vidNewName;

	}

	/**
	 * ftp下载文件的方法 *@param ftpConfig
	 * 
	 * @param remotePath FTP服务器上的相对路径
	 * @param fileName   要下载的文件名
	 * @param localPath  下载后保存到本地的路径
	 * @return 若上传成功，返回
	 * @throws IOException
	 */
	public static boolean pictureFtpDowmload(FtpConfig ftpConfig, String remotePath, String fileName, String localPath)
			throws IOException {

		if (!(ftpConfig != null && ObjectEmptyUtils.isEmptyString(fileName)
				&& ObjectEmptyUtils.isEmptyString(localPath)))
			return false;

		boolean flag = downloadFile(ftpConfig.getFtpAddress(), ftpConfig.getFtpPort(), ftpConfig.getFtpUsername(),
				ftpConfig.getFtpPassword(), remotePath, fileName, localPath);

		if (!flag)
			return false;

		return true;
	}

	/**
	 * title videoFtpDowmload 视频下载 ftp下载文件的方法 *@param ftpConfig
	 * 
	 * @param remotePath FTP服务器上的相对路径
	 * @param fileName   要下载的文件名
	 * @param localPath  下载后保存到本地的路径
	 * @return 若上传成功，返回
	 * @throws IOException
	 */
	public static boolean videoFtpDowmload(FtpConfig ftpConfig, String remotePath, String fileName, String localPath)
			throws IOException {

		if (!(ftpConfig != null && ObjectEmptyUtils.isEmptyString(fileName)
				&& ObjectEmptyUtils.isEmptyString(localPath)))
			return false;

		boolean flag = downloadFile(ftpConfig.getFtpAddress(), ftpConfig.getFtpPort(), ftpConfig.getFtpUsername(),
				ftpConfig.getFtpPassword(), remotePath, fileName, localPath);

		if (!flag)
			return false;

		return true;
	}

	/*
	 * fileName 文件的目录 ftpDir 文件的目录
	 */
	public static boolean ftpDeleteFile(String FileName, String ftpDir) {

		if (ObjectEmptyUtils.isEmptyString(FileName) || ObjectEmptyUtils.isEmptyString(ftpDir))
			return false;

		FTPClient ftp = null;
		try {

			FtpConfig config = FtpConfig.getInstance();
			if (config != null) {
				ftp = new FTPClient();
				boolean isLoginSuccess = ftpLogin(ftp, config.getFtpAddress(), Integer.parseInt(config.getFtpPort()),
						config.getFtpUsername(), config.getFtpPassword());

				if (!isLoginSuccess)
					return false;

				ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
				ftp.makeDirectory(ftpDir);
				ftp.changeWorkingDirectory(ftpDir);

				boolean success = ftp.deleteFile(FileName);
				ftp.logout();
				return success;
			} else {
				return false;
			}
		} catch (IOException e) {
			logger.error(e.getMessage());
		} finally {
			if (ftp.isConnected()) {
				try {
					ftp.disconnect();
				} catch (IOException ioe) {
					logger.error(ioe.getMessage());
				}
			}
		}
		return false;
	}

	/**
	 * Description: 向FTP服务器上传文件
	 * 
	 * @param host     FTP服务器hostname
	 * @param ftpPort  FTP服务器端口
	 * @param username FTP登录账号
	 * @param password FTP登录密码
	 * @param basePath FTP服务器基础目录
	 * @param filePath FTP服务器文件存放路径。例如分日期存放：/2015/01/01。文件的路径为basePath+filePath
	 * @param filename 上传到FTP服务器上的文件名
	 * @param input    输入流
	 * @return 成功返回true，否则返回false
	 */
	public static boolean uploadFile(String host, String ftpPort, String username, String password, String basePath,
			String filePath, String filename, InputStream input) {

		if (!(host != null && ftpPort != null && username != null && password != null && filePath != null
				&& filename != null && input != null))
			return false;

		FTPClient ftp = null;
		try {

			int port = Integer.parseInt(ftpPort);
			ftp = new FTPClient();
			// 连接Ftp服务器
			boolean isSeccess = ftpLogin(ftp, host, port, username, password);
			if (!isSeccess)
				return false;

			// 切换到上传目录
			if (filePath != null && basePath != null && !ftp.changeWorkingDirectory(basePath + filePath)) {
				// 如果目录不存在创建目录
				String[] dirs = filePath.split("/");
				StringBuffer tempPath = new StringBuffer(basePath);
				for (String dir : dirs) {
					if (null == dir || "".equals(dir)) {
						continue;
					}
					tempPath.append("/").append(dir);
					// 判定文件夹是否存在，不存在直接创建
					if (!ftp.changeWorkingDirectory(tempPath.toString())) {
						if (!ftp.makeDirectory(tempPath.toString())) {
							return false;
						} else {
							ftp.changeWorkingDirectory(tempPath.toString());
						}
					}
				}
			}

			// 初始化FT服务器
			initFTP(ftp);

			//linux 需要开启这个方法，才能在外网的情况下上传文件。
			ftp.enterLocalActiveMode();
			// 上传文件
			if (!ftp.storeFile(filename, input)) {
				return false;
			}

			input.close();
			// 登出，断开连接
			ftp.logout();
		} catch (IOException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		} finally {
			if (ftp.isConnected()) {
				try {
					ftp.disconnect();
				} catch (IOException ioe) {
				}
			}
		}
		return true;
	}

	/**
	 * Description: 从FTP服务器下载文件
	 * 
	 * @param host       FTP服务器hostname
	 * @param port       FTP服务器端口
	 * @param username   FTP登录账号
	 * @param password   FTP登录密码
	 * @param remotePath FTP服务器上的相对路径
	 * @param fileName   要下载的文件名
	 * @param localPath  下载后保存到本地的路径
	 * @return
	 */
	public static boolean downloadFile(String host, String ftpPort, String username, String password, String remotePath,
			String fileName, String localPath) {

		if (!(host != null && ftpPort != null && username != null && password != null && fileName != null))
			return false;

		FTPClient ftp = null;

		OutputStream os = null;
		try {

			ftp = new FTPClient();
			int port = Integer.parseInt(ftpPort);
			ftp = new FTPClient();
			// 连接Ftp服务器
			boolean isSeccess = ftpLogin(ftp, host, port, username, password);
			if (!isSeccess)
				return false;

			// 转移到FTP服务器目录
			ftp.changeWorkingDirectory(FtpConfig.getInstance().getFtpBasepath() + remotePath);
			FTPFile[] fs = ftp.listFiles();

			if (fs != null && fs.length != 0) {
				int i = 0;
				for (FTPFile ff : fs) {
					if (ff.getName().equals(fileName)) {
						i++;
						File localFile = new File(localPath + File.separator + ff.getName());
						os = new FileOutputStream(localFile);
						ftp.retrieveFile(ff.getName(), os);
					}
				}
				if (i == 0)
					return false;
			}
			ftp.logout();
		} catch (IOException e) {
			logger.error(e.getMessage());
			return false;
		} finally {
			if (ftp.isConnected() && os != null) {
				try {
					os.flush();
					os.close();
					ftp.disconnect();
				} catch (IOException ioe) {
					logger.error(ioe.getMessage());
					return false;
				}
			}
		}
		return true;
	}

	private static boolean ftpLogin(FTPClient ftp, String host, int port, String username, String password)
			throws IOException {

		// 连接FTP服务器(如果采用默认端口，可以使用ftp.connect(host)的方式直接连接FTP服务器)
		ftp.connect(host, port);
		// 登录
		ftp.login(username, password);

		if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
			ftp.disconnect();
			return false;
		}

		return true;
	}

	public static FTPClient initFTP(FTPClient ftp) throws IOException {

		ftp.setFileType(FTPClient.BINARY_FILE_TYPE);

		ftp.setControlEncoding("GBK");
		// 设置缓冲区上传速度为10M，默认为1K
		ftp.setBufferSize(1024 * 1024 * 10);
		// 设置上传方式位字节  
		ftp.setFileType(FTP.BINARY_FILE_TYPE);
		// Switch to passive mode 这个设置允许被动连接--访问远程ftp时需要
		ftp.setRemoteVerificationEnabled(false);
		ftp.enterLocalPassiveMode();

		FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
		ftp.configure(conf);

		return ftp;
	}

}
